package com.brillilab.starter.aspect;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.brillilab.common.constant.KeyProfixConstant;
import com.brillilab.common.redis.RedisCache;
import com.brillilab.common.utils.DateUtil;
import com.brillilab.common.utils.DigestUtils;
import com.brillilab.common.utils.IPUtil;
import com.brillilab.domain.enums.lab.UserEnum;
import com.brillilab.domain.po.system.LogManage;
import com.brillilab.domain.po.user.Users;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.domain.vo.user.UserInviteApplyInfoVo;
import com.brillilab.domain.vo.user.UserLogin;
import com.brillilab.service.core.system.ILogManageService;
import com.brillilab.service.core.user.IUsersService;
import com.brillilab.starter.constant.StarterConstant;
import com.brillilab.starter.entity.req.user.UserRegisterReq;

import lombok.extern.slf4j.Slf4j;

/**
 * 系统日志切面
 * 
 * @author LJ
 */
@Slf4j
@Aspect
@Component
public class LogManageAspect {

	@Resource
	private RedisCache redisCache;

	@Resource
	private ILogManageService logManageService;
	@Resource
	private IUsersService usersService;

	@Pointcut("@annotation(com.brillilab.starter.aspect.AspectLog)")
	public void logPointCut() {

	}

	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		Object result = null;
		LogManage logManage = new LogManage();
		try {
			// 获取请求对象
			RequestAttributes ra = RequestContextHolder.getRequestAttributes();
			ServletRequestAttributes sra = (ServletRequestAttributes) ra;
			HttpServletRequest request = sra.getRequest();
			// 获取用户信息
			String token = request.getHeader(StarterConstant.TOKEN);
			if (StringUtils.isNotBlank(token)) {
				UserInfoVo userVo = (UserInfoVo) redisCache.getObj(KeyProfixConstant.TOKEN + token);
				if (userVo != null) {
					logManage.setUserId(userVo.getId());
					logManage.setMobile(userVo.getMobile());
				}
			}
			// 获取请求信息
			logManage.setIpAddr(IPUtil.getIpAddr(request));
			logManage.setRequestUrl(request.getRequestURI());
			logManage.setRequestMethod(request.getMethod());
			logManage.setRequestTime(DateUtil.dateString(new Date(), "yyyy-MM-dd HH:mm:ss"));
			Object[] args = joinPoint.getArgs();
			if (args != null && args.length > 0) {
				List<Object> list = new ArrayList<>();
				for (Object o : args) {
					if (!(o instanceof HttpServletRequest) && !(o instanceof HttpServletResponse)) {
						if (logManage.getRequestUrl().contains("/user/accountLogin") && o instanceof UserLogin) {
							UserLogin login = (UserLogin) o;
							if (logManage.getRequestUrl().contains("/user/accountLoginEncode")) {
								String mobile = DigestUtils.base64Decode(login.getMobile());
								login.setMobile(mobile);
								String password = DigestUtils.base64Decode(login.getPassword());
								login.setPassword(password);
							}
							Users users = usersService.selectUser(login.getMobile(), UserEnum.State.NORMAL.getValue());
							if (users != null) {
								logManage.setUserId(users.getId());
								logManage.setMobile(users.getMobile());
								logManage.setLogType("Login");
							}
							list.add(login);
						} else if ((logManage.getRequestUrl().contains("/user/register")
								|| logManage.getRequestUrl().contains("/user/emRegister")
								|| logManage.getRequestUrl().contains("/user/cardRegister"))
								&& o instanceof UserRegisterReq) {
							UserRegisterReq register = (UserRegisterReq) o;
							logManage.setUserId(null);
							logManage.setMobile(register.getMobile());
							logManage.setLogType("Register");
							list.add(register);
						} else if ((logManage.getRequestUrl().contains("/user/addLabMemberAudit")
								|| logManage.getRequestUrl().contains("/userInviteAudit/submitLabMemberAudit")
								|| logManage.getRequestUrl().contains("/userInviteAudit/addLabMemberAudit"))
								&& o instanceof UserInviteApplyInfoVo) {
							UserInviteApplyInfoVo register = (UserInviteApplyInfoVo) o;
							logManage.setUserId(null);
							logManage.setMobile(register.getMobile());
							logManage.setLogType("Register");
							list.add(register);
						} else {
							list.add(o);
						}
					}
				}
				logManage.setRequestBody(JSON.toJSONString(list));
			}
			long startTime = System.currentTimeMillis();
			result = joinPoint.proceed();
			long endTime = System.currentTimeMillis();

			// 获取响应信息
			logManage.setResponseBody(JSON.toJSONString(result));
			logManage.setTimes(endTime - startTime);
			logManage.setSuccess(true);
		} catch (Exception ex) {
			// 获取异常信息
			logManage.setSuccess(false);
			logManage.setResponseBody(JSON.toJSONString(ex.getMessage()));
			throw ex;
		} finally {
			saveLog(logManage);
		}
		return result;
	}

	public void saveLog(LogManage logManage) {
		if (logManage != null) {
			new Thread(() -> {
				String str = logManage.getUserId() + logManage.getRequestUrl();
				if (logManage.isSuccess()) {
					if ("Login".equals(logManage.getLogType())) {
						logManageService.addLoginLog(logManage);
					} else if ("Register".equals(logManage.getLogType())) {
						logManageService.addRegisterLog(logManage);
					}
//					log.info("切面日志: [{}]  {}", str, JSON.toJSONString(logManage));
				} else {
//					log.error("切面日志: [{}]  {}", str, JSON.toJSONString(logManage));
				}
			}).start();
		}
	}
}
